package net.minecraft.src;

import java.util.*;

public class BlockConductiveLamp extends Block
{
	private static  Set<Coords>  a;
    private boolean lampActive;
    private static ArrayList <Coords> lamps = new ArrayList<Coords>(  );
    private static boolean lock = false;
    
    private static ArrayList <BlockLampSet> lampsGroups = new ArrayList <BlockLampSet>();
    
    public int getRenderBlockPass()
    {
        return 0;
    }

    protected BlockConductiveLamp(int i, int j, boolean flag)
    {
        super(i, j,Material.glass);
        lampActive = false;
        lampActive = flag;
    }
    
    public boolean isOpaqueCube()
    {
        return false;
    }

    public boolean shouldSideBeRendered(IBlockAccess iblockaccess, int i, int j, int k, int l)
    {
        int i1 = iblockaccess.getBlockId(i, j, k);
        if ( i1 == blockID)
        {
            return false;
        }
        else
        {
            return super.shouldSideBeRendered(iblockaccess, i, j, k, l);
        }
    }
    
    public int tickRate()
    {
        return 1;
    }

    public void onBlockAdded(World world, int i, int j, int k)
    {
    	
        if (world.getBlockMetadata(i, j, k) == 0)
        {
            super.onBlockAdded(world, i, j, k);
            determineSetForCoord(world, i, j, k);
            world.scheduleBlockUpdate(i, j, k, blockID, tickRate());

        }
        

    }
 
    public void onBlockRemoval(World world, int i, int j, int k)
    {

    	super.onBlockRemoval(world, i, j, k);
    	onLampRemove(new Coords(i,j,k));
 
    }

    public boolean isPoweringTo(IBlockAccess iblockaccess, int i, int j, int k, int l)
    {
    	return false;
    }

    private boolean func_30002_h(World world, int i, int j, int k)
    {
 
        if ( world.isBlockIndirectlyProvidingPowerTo(i, j - 1, k, 0))
        {
            return true;
        }
        if (world.isBlockIndirectlyProvidingPowerTo(i, j, k - 1, 2))
        {
            return true;
        }
        if (world.isBlockIndirectlyProvidingPowerTo(i, j, k + 1, 3))
        {
            return true;
        }
        if (world.isBlockIndirectlyProvidingPowerTo(i - 1, j, k, 4))
        {
            return true;
        }
        return world.isBlockIndirectlyProvidingPowerTo(i + 1, j, k, 5);
    }

    public void updateTick(World world, int i, int j, int k, Random random)
    {
        boolean flag = func_30002_h(world, i, j, k);
        
        updatePowerStatus(world, i, j, k);
        flag = getCurrentPower( i, j, k);
       
  
       // for (; torchUpdates.size() > 0 && world.getWorldTime() - ((RedstoneUpdateInfo)torchUpdates.get(0)).updateTime > 100L; torchUpdates.remove(0)) { }
        if ( !flag  &&  lampActive )
        {
                world.setBlockAndMetadataWithNotify(i, j, k, mod_AsPj.conductiveLampIdle.blockID, world.getBlockMetadata(i, j, k));
        }
        else if (flag && !lampActive )
        {
                 world.setBlockAndMetadataWithNotify(i, j, k, mod_AsPj.conductiveLampActive.blockID, world.getBlockMetadata(i, j, k));
        }
    }
    
    public void onNeighborBlockChange(World world, int i, int j, int k, int l)
    {
        super.onNeighborBlockChange(world, i, j, k, l);
        world.scheduleBlockUpdate(i, j, k, blockID, tickRate());
    }

    public boolean isIndirectlyPoweringTo(World world, int i, int j, int k, int l)
    {
    	
    	if ( 
    			    world.getBlockId(i, j, k) == mod_AsPj.conductiveLampActive.blockID 
    			||  world.getBlockId(i, j, k) == mod_AsPj.conductiveLampIdle.blockID 
    			&&  blockID == mod_AsPj.conductiveLampActive.blockID 
    			)
    		return  false;
    	else			
    		return  false;

    }

    public int idDropped(int i, Random random, int j)
    {
        return mod_AsPj.conductiveLampIdle.blockID;
    }

    public boolean canProvidePower()
    {
        return false;
    }
    
    public boolean addToNeighBourLamps(Coords lampCoords)
    {
    	
    	ListIterator<Coords> iterator = lamps.listIterator();
    	while(iterator.hasNext())
    	{
    		if (iterator.next().equals(lampCoords))
    			return false;

    		//System.out.println(itr.next());
    	}
    	lamps.add(lampCoords);
    	return true;
    	//notify all neighbour
    }
    /*
  
   */
    
    private ArrayList<Coords> createNeighbours(World world,Coords centerLamp)
    {
    	ArrayList<Coords> neighbours = new ArrayList<Coords>();
    	
    	Coords temp = new Coords(centerLamp.x, centerLamp.y - 1, centerLamp.z);
    	if ( isThisLamp(world,temp) )
    		neighbours.add( temp );

    	temp = new Coords(centerLamp.x, centerLamp.y + 1, centerLamp.z);
    	if ( isThisLamp(world,temp) )
    		neighbours.add( temp );    	

    	temp = new Coords(centerLamp.x - 1, centerLamp.y, centerLamp.z);
    	if ( isThisLamp(world,temp) )
    		neighbours.add( temp );        	

    	temp = new Coords(centerLamp.x + 1, centerLamp.y, centerLamp.z);
    	if ( isThisLamp(world,temp) )
    		neighbours.add( temp );    

    	temp = new Coords(centerLamp.x, centerLamp.y, centerLamp.z - 1);
    	if ( isThisLamp(world,temp) )
    		neighbours.add( temp );    

    	temp = new Coords(centerLamp.x, centerLamp.y, centerLamp.z + 1);
    	if ( isThisLamp(world,temp) )
    		neighbours.add( temp );    

    	return neighbours;
    }
    /*

    }
    */
    private Coords getCoordsFromSet(BlockLampSet  lampSet, Coords matchCoord )
    {
    	if(     lampSet == null
    		||  matchCoord == null
    	  )
    		return  null;
    	
		Iterator<Coords> setIterator = lampSet.lampsCoordsSet.iterator();
		
		while(setIterator.hasNext())
		{ 
			Coords  coordsInSet=setIterator.next();
			if(coordsInSet.equals(matchCoord))
				return coordsInSet;
			
		}
		return  null;
    }
    
    private BlockLampSet isLampInGlobalSet(Coords lampCoords)
    {
				ListIterator<BlockLampSet> listIterator = lampsGroups.listIterator();
				while(listIterator.hasNext())
				{
					BlockLampSet temporary = listIterator.next();
					Iterator<Coords> setIterator = temporary.lampsCoordsSet.iterator();
					
					while(setIterator.hasNext())
					{ 
						if(setIterator.next().equals(lampCoords))
							return temporary;
						
					}
				
				}
	 	return  null;
}
    
    private boolean  isLampInGivenSet( BlockLampSet lampSet, Coords lampCoords)
    {
		Iterator<Coords> setIterator = lampSet.lampsCoordsSet.iterator();
		
		while(setIterator.hasNext())
		{ 
			if(setIterator.next().equals(lampCoords))
				return true;
		}
		return  false;
    	
    }
    
    private  boolean getCurrentPower(int i,int j, int k)
    {
    	Coords lampCoords =  new Coords(i,j,k);
    	return isLampInGlobalSet(lampCoords).powered;
    }
    
    private void updatePowerStatus(World world, int i,int j, int k)
    {
        boolean flag = func_30002_h(world, i, j, k);
    	Coords lampCoords =  new Coords(i,j,k);
    	
    	BlockLampSet lampSet = determineSetForCoord(world,i,j,k);
		lampSet.powered = false;
		Iterator<Coords> setIterator = lampSet.lampsCoordsSet.iterator();
		while(setIterator.hasNext())
		{ 
			Coords temp= setIterator.next();
			if(func_30002_h(world,temp.x,temp.y,temp.z))
					lampSet.powered = true;
			
		}
    }
    //iteracja  po  wszystkich  w  celu  update  czy  jeszcze  co�  zostalo   
    private     void removeAndUpdatePowerStatus(World world, int i,int j, int k)
    {
    	Coords lampCoords =  new Coords(i,j,k);
    	
    	BlockLampSet lampSet = determineSetForCoord(world,i,j,k);
    	
    	lampSet.lampsCoordsSet.remove(lampCoords);
		Iterator<Coords> setIterator = lampSet.lampsCoordsSet.iterator();
		
		lampSet.powered = false;
		while(setIterator.hasNext())
		{ 
			Coords temp= setIterator.next();
			if(func_30002_h(world,temp.x,temp.y,temp.z))
					lampSet.powered = true;
			
		}
    }
    
    
    // zaczynamy  update 
    // size  z  setomanii
    //je�eli  1  to   potwierdz  czy  ktorys  z  sasiad�w  jest  na  secie  
//jezeli  tak   to  kasuj  nowy  set  i  k�adz  go  na   ten  set  jak  wyjdzie 
    /* NOT OPTIMALISED */
private  BlockLampSet  determineSetForCoord(World world, int i,int j, int k)
    {
		Coords lampCoords =  new Coords(i,j,k);
    	BlockLampSet  lampSet = new BlockLampSet();
    	createSetFromLampArea( lampSet, world, lampCoords );
    	if(lampSet.lampsCoordsSet.size() == 0)
    		return isLampInGlobalSet(lampCoords);
    	if(lampSet.lampsCoordsSet.size() == 1)
    	{
    		BlockLampSet lampTempSet= checkNeighboars(world,lampCoords, lampSet.powered);
    		if( lampTempSet != null)
    		{
    			lampsGroups.add(lampTempSet);
    			return lampTempSet;
    		}
    			    	
    	}
    	lampsGroups.add(lampSet);
    	return lampSet;
    }
    
//disassambly  --  remove  i  zobacz  czy  ktorys  sasiad  jest  na 
// zniszczenie seta
//
private void onLampRemove(Coords lampCoords)
{
	BlockLampSet lampSet = isLampInGlobalSet(lampCoords);
	lampsGroups.remove(lampSet);
}
    // przejscie  po wszystkich 
    private BlockLampSet checkNeighboars(World world,Coords lampCoords, boolean powered)
    {
    	
    	ArrayList<Coords> neighbours = createNeighbours(world,lampCoords);
    	Iterator<Coords> iterator= neighbours.iterator();

    	BlockLampSet lampTempSet= null;
    	while(iterator.hasNext())
    	{
    		BlockLampSet temporary = isLampInGlobalSet(iterator.next()); 
    		if( temporary != null)
    		{
	    		lampsGroups.remove(temporary);
	    		lampTempSet = mergeSets(lampTempSet,temporary);

	    		if( powered )
	    			lampTempSet.powered = powered;
    			lampTempSet.lampsCoordsSet.add(lampCoords);
    		}
    	}
    	return lampTempSet;
    }
    
    private BlockLampSet mergeSets(BlockLampSet target,BlockLampSet source)
    {
    	if(target == null)
    	{
    		target = source;
    	}
    	else
    	{
    		if(source.powered)
    			target.powered = source.powered;
    		
    		target.lampsCoordsSet.addAll(source.lampsCoordsSet);
    	}
    	return target;
    }
    
    private boolean  isThisLamp(World world,Coords lampCoords)
    {
    	
   	 return
		        world.getBlockId(lampCoords.x, lampCoords.y, lampCoords.z) == mod_AsPj.conductiveLampActive.blockID 
			||  world.getBlockId(lampCoords.x, lampCoords.y, lampCoords.z) == mod_AsPj.conductiveLampIdle.blockID;    	
    }
    
    //  setomania
    // sprawdz  czy  jestes  lampa
    // sprawdz  czy  jestes na  setach isLamp(World world,BlockLampCoords lampCoords)
    // je�eli  nie  to  dodaj  sie  do  setu   aktualnego  i  spaceruj po  sasiadach rekurencja
    // je�eli  tak  wyjdz
    private  void createSetFromLampArea( BlockLampSet  lampSet, World world, Coords lampCoords )
    {
    	if(!isThisLamp(world,lampCoords))
    		return;
    	BlockLampSet temporaryLampSet =  isLampInGlobalSet(lampCoords);
    	if( temporaryLampSet != null )
    		return;
    	
    	if (isLampInGivenSet(lampSet, lampCoords) )
    		return;
    	boolean flag = func_30002_h(world, lampCoords.x, lampCoords.y, lampCoords.z);

    	
    	if(flag)
    		lampSet.powered = flag;
    	lampSet.lampsCoordsSet.add(lampCoords);
    	
    	ArrayList<Coords> neighbours = createNeighbours(world,lampCoords);
    	Iterator<Coords> iterator= neighbours.iterator();
    	
    	while(iterator.hasNext())
    	{
    		createSetFromLampArea( lampSet, world, iterator.next() );
    	}
    }
    
}
